﻿using System;
using System.ComponentModel;
using System.Drawing;
using System.IO;
using System.Runtime.InteropServices;
using System.Windows.Forms;
using Asztal.Szótár;
using NExplorer.Properties;
using NExplorer.ThirdParty;
using TreeView=System.Windows.Forms.TreeView;

namespace NExplorer
{
	internal enum IconSize
	{
		Small = 1,
		Large = 0
	}

	internal class Utilities
	{
		[DllImport("shell32.dll")]
		private static extern IntPtr SHGetFileInfo(string pszPath, uint dwFileAttributes, ref SHFILEINFO psfi, uint cbSizeFileInfo, uint uFlags);

        [DllImport("uxtheme.dll", ExactSpelling = true, CharSet = CharSet.Unicode)]
        public static extern int SetWindowTheme(IntPtr hWnd, String pszSubAppName, String pszSubIdList);

        [DllImport("user32.dll", CharSet = CharSet.Auto)]
        public static extern IntPtr SendMessage (IntPtr hWnd, int msg, int wParam, int lParam);

        [DllImport("dwmapi.dll")]
        private static extern int DwmIsCompositionEnabled(out bool enabled);
 
		private const uint SHGFI_ICON = 0x100;
		private const uint SHGFI_TYPENAME = 0x400;

		[StructLayout(LayoutKind.Sequential)]
		public struct SHFILEINFO
		{
			public IntPtr hIcon;
			public IntPtr iIcon;
			public uint dwAttributes;
			[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)]
			public string szDisplayName;
			[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 80)]
			public string szTypeName;
		}

		private static bool _showHiddenFiles;

		static Utilities()
		{
			Settings.Default.PropertyChanged += Default_PropertyChanged;
			_showHiddenFiles = Settings.Default.ShowHiddenFiles;
		}

	    public static bool IsCompositionEnabled
	    {
	        get
	        {
	            bool enabled;
	            DwmIsCompositionEnabled(out enabled);
	            
                return enabled;
	        }
	    }

	    private static bool IsVistaOrLater
	    {
            get { return Environment.OSVersion.Platform == PlatformID.Win32NT && Environment.OSVersion.Version.Major >= 6; }
	    }

	    // Thanks to Nicholas Kwan for this
        // http://www.codeproject.com/KB/vista/themedvistacontrols.aspx
        public static void SetExplorerStyle(Control c)
        {
            SetWindowTheme(c.Handle, "Explorer", null); 

            if (c is TreeView)
            {
                //// Fade
                //SendMessage(c.Handle, 0x1100 + 44, 0x0040, 0x0040);
                // Auto-scroll
                SendMessage(c.Handle, 0x1100 + 44, 0x0020, 0x0020);
            }
        }

		public static void GetFileTypeAndIcon(string filename, IconSize size, out string description, out Icon icon)
		{
			SHFILEINFO info = new SHFILEINFO();
			SHGetFileInfo(filename, 0, ref info, (uint)Marshal.SizeOf(info), SHGFI_TYPENAME | SHGFI_ICON | (uint)size);

			description = info.szTypeName;
			
			try
			{
				// May fail if file no longer exists. Prefer to handle this exceptional case
				// rather than take the overhead of checking for file every call, of which there are many.
				icon = Icon.FromHandle(info.hIcon);
			}
			catch 
			{
				icon = null;
			}
		}

		public static Icon GetIcon(string filename, IconSize size)
		{
			Icon icon;

			// TODO: Consider using SHGFI_USEFILEATTRIBUTES
			SHFILEINFO info = new SHFILEINFO();
			SHGetFileInfo(filename, 0, ref info, (uint)Marshal.SizeOf(info), SHGFI_ICON | (uint)size);

			try
			{
				icon = Icon.FromHandle(info.hIcon);
			}
			catch 
			{
				icon = null;
			}

			return icon;
		}

		static void Default_PropertyChanged(object sender, PropertyChangedEventArgs e)
		{
			if (e.PropertyName == "ShowHiddenFiles")
			{
				_showHiddenFiles = Settings.Default.ShowHiddenFiles;
			}
		}

		public static bool CanShowFileSystemItem(FileSystemInfo fileSystemInfo)
		{
			bool show = false;

			if (fileSystemInfo != null)
			{
			    DirectoryInfo dirInfo = fileSystemInfo as DirectoryInfo;

                // Always show root dirs.
			    if (dirInfo != null && dirInfo.Parent == null)
			    {
			        show = true;
			    }
				else
			    {
			        show = _showHiddenFiles || ((fileSystemInfo.Attributes & FileAttributes.Hidden) != FileAttributes.Hidden);
			    }
			}
			
			return show;
		}

		public static ToolStripRenderer GetToolBarRenderer()
		{
			if (IsVistaOrLater)
			{
				return new WindowsVistaRenderer();
			}
			else
			{
				return new ToolStripSystemRenderer();
			}
		}

		public static ToolStripRenderer GetMenuStripRenderer()
		{
			ToolStripRenderer renderer = null;
	
			if (IsVistaOrLater)
			{
				renderer = new UXThemeToolStripRenderer();
			}

			return renderer;
		}

		public static FileSystemInfo CreateFileSystemInfo(string path)
		{
			FileSystemInfo info;

			if (Directory.Exists(path))
			{
				info = new DirectoryInfo(path);	
			}
			else if (File.Exists(path))
			{
				info = new FileInfo(path);
			}
			else
			{
				info = null;
			}

			return info;
		}
	}
}
